package work2;

import java.util.Scanner;

/*
*
*编程实现控制台版并支持两人对战的五子棋游戏。

（1）绘制棋盘 - 写一个成员方法实现

（2）提示黑方和白方分别下棋并重新绘制棋盘 - 写一个成员方法实现。

（3）每当一方下棋后判断是否获胜 - 写一个成员方法实现。
*
*
* */
public class Test2 {
    private static String str[][] = new String[17][17]; //定义棋牌的数组
    private static boolean isBlack = false;
    private static final String BLACK = "  B" ;
    private static final String WRITE = "  W";
    public static void main(String arg[]){
        Scanner scanner = new Scanner(System.in);
        createView();
        chess(scanner);
    }


    //绘制棋盘
    private static void createView(){
        //定义一个17行17列的二维数组
        //先将第一个数组的值赋值
        str[0] = new String[]{" ","  0","  1","  2","  3","  4","  5","  6","  7","  8","  9","  a","  b","  c","  d","  e","  f"};
        setArr(str[1],"0");

        setArr(str[2],"1");
        setArr(str[3],"2");
        setArr(str[4],"3");
        setArr(str[5],"4");
        setArr(str[6],"5");
        setArr(str[7],"6");
        setArr(str[8],"7");
        setArr(str[9],"8");
        setArr(str[10],"9");
        setArr(str[11],"a");
        setArr(str[12],"b");
        setArr(str[13],"c");
        setArr(str[14],"d");
        setArr(str[15],"e");
        setArr(str[16],"f");
        for (int i = 0; i < str.length; i++) {
            for (int i1 = 0; i1 < str[i].length; i1++) {
                System.out.print(str[i][i1]);
            }
            System.out.println("");
        }

    }

    //给其他数组赋值，传入一个字段，当做首个打印的文字
    public static void setArr(String strings[],String str){
        String arr[] = new String[17];
        for (int i = 0; i < 17; i++) {
            //如果i为0，则给第一个数据赋值
            if (i == 0){
                arr[i] = str;
                //其他字段全部赋予 +  这个字符
            } else {
                arr[i] = "  +";
            }
        }
        System.arraycopy(arr,0,strings,0,arr.length);
    }

    //提示黑方和白方分别下棋并重新绘制棋盘 - 写一个成员方法实现。
    private static void chess(Scanner scanner){
        //告知是黑棋还是白棋输入
        if (isBlack){
            System.out.println("黑棋请输入落子位置如(3 2)");
        } else {
            System.out.println("白棋请输入落子位置如(3 2)");

        }
        int x =  scanner.nextInt();
        int y = scanner.nextInt();
        //检查棋子位置是否异常
        if (checkPosition(x,y)) {
            chess(scanner);
            return;
        }
        if (isBlack){
            str[x][y] = BLACK;
        } else {
            str[x][y] = WRITE;
        }

        //输入结束重新绘制棋牌
        for (int i = 0; i < str.length; i++) {
            for (int i1 = 0; i1 < str[i].length; i1++) {
                System.out.print(str[i][i1]);
            }
            System.out.println("");
        }
        //判断是否存在五子连珠
        if (checkSuccessNew1(x,y)) {
            if (isBlack){
                System.out.println("游戏结束黑棋胜利");
            } else {
                System.out.println("游戏结束白棋胜利");
            }
        } else {
            if (isBlack){
                isBlack = false;
            } else {
                isBlack = true;
            }
            chess(scanner);
        }

    }
    //判断棋盘位置是否有棋子,或者判断棋子位置是否超出棋牌
    private static boolean checkPosition(int x,int y){
        if (y > 16 || y < 1 || x > 16 || x < 1){
            System.out.println("棋子位置超出棋牌，请重新输入位置");
            return true;
        }
        if (str[x][y].equals(BLACK) || str[x][y].equals(WRITE)){
            System.out.println("该位置已有棋子，请重新输入位置");
            return true;
        }
        return false;
    }
   // 每当一方下棋后判断是否获胜 - 写一个成员方法实现。
    //觉得做所有循环太麻烦 就没写了
    private static boolean checkSuccess() {
        String checkStr = "";
        if (isBlack) {
            checkStr = BLACK;
        } else {
            checkStr = WRITE;
        }
        //判断是否获胜需判断4次  一次是横向  一次纵向  一次左斜对角一次右斜对角

        int count = 0;
        int x1 = 1;
        int y1 = 1;


        //这个判断是x轴一直在改变  y轴不变  然后判断是否有五子连珠
        while (true) {
            String value = str[x1][y1];
            //如果相同，则继续向后对比
            if (value.equals(checkStr)) {
                count++;
                if (count == 5){
                    return true;
                }
            } else {
                if (x1 == 16){
                    x1 = 1;
                    y1 ++;
                    count = 0;
                }
            }
            x1 = x1 + 1;
            //当y执行到最后一行时，退出循环，因为没有五子连珠
            if (y1 == 17){
                break;
            }
        }
        int x2 = 1;
        int y2 = 1;
        count = 0;
        //这个判断是y轴一直在改变  x轴不变  然后判断是否有五子连珠
        while (true) {
            String value = str[x2][y2];
            //如果相同，则继续向后对比
            if (value.equals(checkStr)) {
                count++;
                if (count == 5){
                    return true;
                }
            } else {
                if (y2 == 16){
                    y2 = 1;
                    x2 ++;
                    count = 0;
                }
            }
            y2++;
            //当y执行到最后一行时，退出循环，因为没有五子连珠
            if (x2 == 17){
                break;
            }
        }


        return false;
    }
    // 每当一方下棋后判断是否获胜 - 写一个成员方法实现。新实现，不需要判断太多，
    // 只需要判断新下的棋子有没有五子连珠就行，这样可以减少循环的次数
    //写着写着更复杂了，这个方法也放弃
    private static boolean checkSuccessNew(int x ,int y) {
        String checkStr = "";
        if (isBlack) {
            checkStr = BLACK;
        } else {
            checkStr = WRITE;
        }

        //横向或纵向是否成功
        for (int i = 1; i < 17; i++) {
            //x为横向坐标，直接判断x这行有没有五子连珠
            if (i + 4 < 17){
                if (str[x][i].equals(checkStr) && str[x][i+1].equals(checkStr) && str[x][i+2].equals(checkStr) && str[x][i+3].equals(checkStr) && str[x][i+4].equals(checkStr)){
                    return true;
                }
                //y为纵向向坐标，直接判断y这列有没有五子连珠
                if (str[i][y].equals(checkStr) && str[i+1][y].equals(checkStr) && str[i+2][y].equals(checkStr) && str[i+3][y].equals(checkStr) && str[i+4][y].equals(checkStr)){
                    return true;
                }
            }
        }
        //然后需要判断交叉是否有5子连珠情况  因为交叉的有几条线不足5个子，所以可以排除
        //从棋盘绘制可以看出，xy想加起码要大于4才能形成五子连珠
        //xy想加小于28才能形成五子连珠
        //斜左方判断
        if (x+y > 4 && x+y <28){

           if (y == 1){
               if (str[x][y].equals(checkStr) && str[x-1][y+1].equals(checkStr) && str[x-2][y+2].equals(checkStr) && str[x-3][y+3].equals(checkStr) && str[x-4][y+4].equals(checkStr)){
                   return true;
               }
           }
            if (y == 2){
                if (str[x][y].equals(checkStr) && str[x+1][y-1].equals(checkStr) && str[x-1][y+1].equals(checkStr) && str[x-3][y+3].equals(checkStr) && str[x-2][y+2].equals(checkStr)){
                    return true;
                }
            }
            if (x == 1){
                if (str[x][y].equals(checkStr) && str[x+1][y-1].equals(checkStr) && str[x+2][y-2].equals(checkStr) && str[x+3][y-3].equals(checkStr) && str[x+4][y-4].equals(checkStr)){
                    return true;
                }
            }
            if (x == 2){
                if (str[x][y].equals(checkStr) && str[x-1][y+1].equals(checkStr) && str[x+2][y-2].equals(checkStr) && str[x+3][y-3].equals(checkStr) && str[x-1][y+1].equals(checkStr)){
                    return true;
                }
            }
            if (str[x][y].equals(checkStr) && str[x-1][y+1].equals(checkStr) && str[x-2][y+2].equals(checkStr) && str[x+1][y-1].equals(checkStr) && str[x+2][y-2].equals(checkStr)){
                return true;
            }
        }
        //斜右方判断
        //从棋盘绘制可以看出，xy想减起码要小于才能形成五子连珠
        if (x-y < 13 && y-x <13){

            if (y == 1 || x == 1){
                if (str[x][y].equals(checkStr) && str[x+1][y+1].equals(checkStr) && str[x+2][y+2].equals(checkStr) && str[x+3][y+3].equals(checkStr) && str[x+4][y+4].equals(checkStr)){
                    return true;
                }
            }
             else  if (y == 2 || x == 2){
                if (str[x][y].equals(checkStr) && str[x-1][y-1].equals(checkStr) && str[x+1][y+1].equals(checkStr) && str[x+3][y+3].equals(checkStr) && str[x+2][y+2].equals(checkStr)){
                    return true;
                }
            } else if(y == 16 || x == 16){
                if (str[x][y].equals(checkStr) && str[x-1][y-1].equals(checkStr) && str[x-2][y-2].equals(checkStr) && str[x-3][y-3].equals(checkStr) && str[x-4][y-4].equals(checkStr)){
                    return true;
                }
            } else if (y == 15 || x == 15){
                if (str[x][y].equals(checkStr) && str[x-1][y-1].equals(checkStr) && str[x-2][y-2].equals(checkStr) && str[x-3][y-3].equals(checkStr) && str[x+1][y+1].equals(checkStr)){
                    return true;
                }
            } else {
                //五子连珠从上到下有10钟情况 


                return true;
            }
        }


        return false;
    }
   //又换了一种思路  判断单方向累计为5次就可以了  比如往左判断有连续count 加上 往右判断有连续也加上  这样就更简单了
    private static boolean checkSuccessNew1(int x,int y){
        int count = 1;
        String checkStr = "";
        if (isBlack){
            checkStr = BLACK;
        } else {
            checkStr = WRITE;
        }
        int indexX = 0;
        int indexY = 0;

        //先判断横向，当前点为1 只要判断到有连续的点就count+1  这样横向判断两次  左边一次右边一次  加起来有五个则表示五子连珠
        for (indexX = x -1;indexX>0;indexX --){
           //如果有相同字符，则count+1
            if (str[indexX][y].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
                //如果不为相同字符，直接不判断了
            } else {
                break;
            }
        }
        //横向向右
        for (indexX = x +1;indexX <=16;indexX ++){
            //如果有相同字符，则count+1
            if (str[indexX][y].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
                //如果不为相同字符，直接不判断了
            } else {
                break;
            }
        }

        //同理，判断纵向 count重置
        count = 1;
        for (indexY = y -1;indexY>0;indexY--){
            if (str[x][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
            } else {
                break;
            }
        }
        for (indexY = y +1;indexY<=16;indexY++){
            if (str[x][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }

            } else {
                break;
            }
        }
        count = 1;
        //然后是交叉判断，两个方向  一个是从左上角到右下角  一个是右上角到左下角
        for (indexX = x-1,indexY = y-1;indexX>0&&indexY >0;indexX--,indexY--){
            if (str[indexX][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
            } else {
                break;
            }
        }
        for (indexX = x+1,indexY = y+1;indexX<=16&&indexY <=16;indexX++,indexY++){
            if (str[indexX][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
            } else {
                break;
            }
        }
        count = 1;
        //第二个方向
        for (indexX = x-1,indexY = y+1;indexX>0&&indexY <=16;indexX--,indexY++){
            if (str[indexX][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
            } else {
                break;
            }
        }
        for (indexX = x+1,indexY = y-1;indexX<=16&&indexY >0;indexX++,indexY--){
            if (str[indexX][indexY].equals(checkStr)){
                count++;
                //5字连珠返回true
                if (count == 5){
                    return true;
                }
            } else {
                break;
            }
        }
        return false;
    }

}
